import {ElMessage} from "element-plus";
import axios, {AxiosInstance, AxiosRequestConfig, Method} from "axios";
import storage from "@/utils/storage";

// 定义接口
interface PendingType {
    url?: string;
    method?: Method;
    params: any;
    data: any;
    cancel: any;
}

class AxiosClass {

    static instance : AxiosClass;
    axiosInstance : AxiosInstance;

    // 取消重复请求
    pending: Array<PendingType> = [];

    CancelToken = axios.CancelToken;

    protected config: AxiosRequestConfig = {
        headers: {
            "Content-Type": "application/x-www-form-urlencoded",
            "Access-Control-Allow-Origin-Type": '*',
        },
        // 请求时长
        timeout: 1000 * 30,
        baseURL: "/api",
        //     ? "测试"
        //     : "正式",
        // 表示跨域请求时是否需要使用凭证
        withCredentials: true,
    }

    public errorHandle(status:number,other:string):void{
        // 状态码判断
        switch (status) {
            case 302: ElMessage.error('接口重定向了！');
                break;
            case 400:
                ElMessage.error("发出的请求有错误，服务器没有进行新建或修改数据的操作==>" + status)
                break;
            // 401: 未登录
            // 未登录则跳转登录页面，并携带当前页面的路径
            // 在登录成功后返回当前页面，这一步需要在登录页操作。
            case 401: //重定向
                ElMessage.error("token:登录失效")
                // storage.remove(store.state.Roles)
                // storage.get(store.state.Roles)
                // router.replace({
                //     path: '/Login',
                // });
                break;
            // 403 token过期
            // 清除token并跳转登录页
            case 403:
                ElMessage.error("登录过期,用户得到授权，但是访问是被禁止的==>" + status)
                // store.commit('token', null);
                // setTimeout(() => {
                //     router.replace({
                //         path: '/Login',
                //     });
                // }, 1000);
                break;
            case 404:
                ElMessage.error("网络请求不存在==>" + status)
                break;
            case 406:
                ElMessage.error("请求的格式不可得==>" + status)
                break;
            case 408: ElMessage.error(" 请求超时！")
                break;
            case 410:
                ElMessage.error("请求的资源被永久删除，且不会再得到的==>" + status)
                break;
            case 422:
                ElMessage.error("当创建一个对象时，发生一个验证错误==>" + status)
                break;
            case 500:
                ElMessage.error("服务器发生错误，请检查服务器==>" + status)
                break;
            case 502:
                ElMessage.error("网关错误==>" + status)
                break;
            case 503:
                ElMessage.error("服务不可用，服务器暂时过载或维护==>" + status)
                break;
            case 504:
                ElMessage.error("网关超时==>" + status)
                break;
            default:
                ElMessage.error("其他错误错误==>" + status)
        }
        console.log(other)
    }

    public removePending(config:AxiosRequestConfig):void{
        for (const key in this.pending) {
            const item: number = +key;
            const list: PendingType = this.pending[key];
            // 当前请求在数组中存在时执行函数体
            if (list.url === config.url && list.method === config.method && JSON.stringify(list.params) === JSON.stringify(config.params) && JSON.stringify(list.data) === JSON.stringify(config.data)) {
                // 执行取消操作
                list.cancel('操作太频繁，请稍后再试');
                // 从数组中移除记录
                this.pending.splice(item, 1);
            }
        }
    }

    protected requestIntercept(){
        this.axiosInstance.interceptors.request.use(
            config => {
                this.removePending(config);
                config.cancelToken = new this.CancelToken((c) => {
                    this.pending.push({ url: config.url, method: config.method, params: config.params, data: config.data, cancel: c });
                });
                config.headers.Authorization = "Bearer " + storage.get("token");
                return config;
            },
            error => {
                ElMessage.error(error.data.error.message);
                return Promise.reject(error);
            }
        )
    }

    protected responseIntercept(){
        // eslint-disable-next-line @typescript-eslint/no-this-alias
        const that= this
        this.axiosInstance.interceptors.response.use(
            function (response) {
                // dataList.show = true
                that.removePending(response.config);
                // 请求成功
                if (response.status === 200 || response.status === 204) {
                    setTimeout(() => {
                        // dataList.show = false
                    }, 400)
                    //请求结果失败
                    if (response.data.code !== 200){
                        ElMessage.error({
                            message:response.data.msg,
                            duration:1000
                        })
                    }
                    return Promise.resolve(response.data);
                } else {
                    return Promise.reject(response);
                }
                // 请求失败
            }, function (error) {

                const {response} = error;
                if (response) {
                    that.errorHandle(response.status, response.data.message);

                    // 超时重新请求
                    const config = error.config;
                    // 全局的请求次数,请求的间隙
                    const [RETRY_COUNT, RETRY_DELAY] = [0, 1000];

                    if (config && RETRY_COUNT) {
                        // 设置用于跟踪重试计数的变量
                        config.__retryCount = config.__retryCount || 0;
                        // 检查是否已经把重试的总数用完
                        if (config.__retryCount >= RETRY_COUNT) {
                            return Promise.reject(response || {message: error.message});
                        }
                        // 增加重试计数
                        config.__retryCount++;
                        // 创造新的Promise来处理指数后退
                        const backoff = new Promise<void>((resolve) => {
                            setTimeout(() => {
                                resolve();
                            }, RETRY_DELAY || 1);
                        });
                        // instance重试请求的Promise
                        return backoff.then(() => {
                            return that.axiosInstance(config);
                        });
                    }

                    return Promise.reject(response);
                } else {
                    // 处理断网的情况
                    // eg:请求超时或断网时，更新state的nretwok状态
                    // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
                    // 后续增加断网情况下做的一些操作
                    // store.commit('networkState', false);
                }
            }
        )
    }

    public createAxios(){
        this.axiosInstance = axios.create(this.config)
        this.requestIntercept()
        this.responseIntercept()
        return this.axiosInstance
    }

    static getInstance(){
        if (!AxiosClass.instance) {
            /* 实例化请求配置 */
            AxiosClass.instance = new AxiosClass()
        }
        return AxiosClass.instance
    }
}

const axiosClass = AxiosClass.getInstance().createAxios()

export default axiosClass;